package com.distribute.core.init;

import cn.hutool.core.util.StrUtil;
import com.distribute.core.constants.CacheConstants;
import com.distribute.core.constants.LocalCacheConstants;
import com.distribute.core.core.CacheManageContext;
import com.distribute.core.utils.SpringContextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;

import java.lang.annotation.Annotation;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * TODO
 *
 * @author chennengcheng
 * @date 2021-09-13 10:59
 * @remark
 */

public class Initializer implements ApplicationContextAware {

    private static final Logger log = LoggerFactory.getLogger(Initializer.class);

    /* 缓存管理服务器 ip  */
    @Value("${dlc.server.ip:}")
    private String dlcServerIp;

    /* 缓存管理服务器 port  */
    @Value("${dlc.server.port:0}")
    private Integer dlcServerPort;

    /* 缓存管理服务器 上报间隔时间  */
    @Value("${dlc.server.reportTime:0}")
    private Integer dlcServerReportTime;

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        SpringContextUtils.applicationContext = applicationContext;
        init();
    }

    public void init (){
        // 初始化一些常量
        initBaseProperty();
        // 先初始化本地缓存
        try {
            CacheManageContext.globalInit();
        } catch (ExecutionException | InterruptedException e) {
            SpringApplication.exit(this.applicationContext);
        }
        //初始化 通知组件
        initNotifyComponent();
        // 初始化netty 服务
        initNettyServerReport();

    }

    public void initNettyServerReport(){
        // 初始化 netty 服务
        if (StringUtils.isEmpty(this.dlcServerIp) || this.dlcServerPort.equals(0)) {
            log.warn("未配置缓存缓存中心管理地址，无法使用内存上报功能。");
            return;
        }

        new Thread(() -> {
            CacheReportClient cacheReportClient = new CacheReportClient(this.dlcServerIp, this.dlcServerPort);
            cacheReportClient.initNettyServer();
        }).start();
    }

    /**
     * 初始化 redis 通知组件
     */
    public void initNotifyComponent(){
        AbstractNotifyComponent abstractNotifyComponent =
                SpringContextUtils.getBean(
                        CacheConstants.notifyOfComponent.getSimpleName(),
                        AbstractNotifyComponent.class);
        abstractNotifyComponent.init();
    }

    /**
     * 基础属性
     */
    public void initBaseProperty(){
        LocalCacheConstants.setIp(getIp());
        LocalCacheConstants.setServiceName(findBootClass());
        LocalCacheConstants.setActiveProfile(getActiveProfile());
        LocalCacheConstants.setReportTime(dlcServerReportTime);
    }

    public String getIp(){
        InetAddress address;
        try {
            address = InetAddress.getLocalHost();
            return address.getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        return null;
    }

    public String getActiveProfile(){
        Environment environment = this.applicationContext.getEnvironment();
        environment.getActiveProfiles();
        if (environment.getActiveProfiles().length > 0) {
            return environment.getActiveProfiles()[0];
        }

        return "";
    }

    @SuppressWarnings("all")
    public String findBootClass() {
        Map<String, Object> annotatedBeans = null;
        try {
            annotatedBeans = this.applicationContext.getBeansWithAnnotation(
                            (Class<? extends Annotation>)
                                    Class.forName(CacheConstants.SPRING_APPLICATION_CLASS));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        String bootStrapName = annotatedBeans.isEmpty() ? null : String.valueOf(annotatedBeans.keySet().toArray()[0]);
        return StrUtil.upperFirst(bootStrapName);
    }


}
